﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Security.Principal;
using System.Drawing;

namespace BattleThis.Core
{
	/// <summary>
	/// Represent a Player in Battle this.
	/// </summary>
	[System.Diagnostics.DebuggerDisplay("Player {Name} {Id}")]
	public class Player : IPrincipal
	{

		#region Variablen
		/// <summary>
		/// Represent a unkown player.
		/// </summary>
		public static readonly Player Unkown = new Player();
		#endregion

		#region Properties
		/// <summary>
		/// Gets the id of the player.
		/// </summary>
		public Guid Id { get; private set; }
		/// <summary>
		/// Gets the name the name of the player.
		/// </summary>
		public string Name { get; private set; }
		/// <summary>
		/// Gets the current army of the player in game.
		/// </summary>
		public List<Unit> Army { get; private set; }
		/// <summary>
		/// Gets or sets the color the color of the player.
		/// </summary>
		/// <value>
		/// The color.
		/// </value>
		public Color Color { get; set; }
		/// <summary>
		/// Gets or sets the player identity.
		/// </summary>
		/// <value>
		/// The player identity.
		/// </value>
		private IIdentity BattleThisIdentity { get; set; }

		#endregion

		#region Methoden
		/// <summary>
		/// Initializes a new instance of the <see cref="Player"/> class.
		/// </summary>
		public Player()
		{
			this.Id = Guid.Empty;
			this.Name = "None";
			this.Army = new List<Unit>();
			this.BattleThisIdentity = AnonymousIdentity.Anonymous;
		}

		/// <summary>
		/// Initializes a new instance of the <see cref="Player"/> class.
		/// </summary>
		/// <param name="id">The id of the player.</param>
		/// <param name="name">The name of the player.</param>
		public Player( Guid id, string name )
		{
			if( Guid.Empty.Equals( id ) ) throw new ArgumentOutOfRangeException( "id is guid empty" );
			if( string.IsNullOrEmpty( name ) ) throw new ArgumentNullException();

			this.Id = id;
			this.Name = name;
			this.Army = new List<Unit>();
			this.BattleThisIdentity = new PlayerIdentity( this.Name );
		}

		/// <summary>
		/// Determines whether this instance is unkown.
		/// </summary>
		/// <returns>
		///   <c>true</c> if this instance is unkown; otherwise, <c>false</c>.
		/// </returns>
		public bool IsUnkown()
		{
			return this.Equals( Player.Unkown );
		}

		/// <summary>
		/// Determines whether the specified <see cref="System.Object"/> is equal to this instance.
		/// </summary>
		/// <param name="obj">The <see cref="System.Object"/> to compare with this instance.</param>
		/// <returns>
		///   <c>true</c> if the specified <see cref="System.Object"/> is equal to this instance; otherwise, <c>false</c>.
		/// </returns>
		public override bool Equals( object obj )
		{
			if( obj is Player )
				return this.Id.Equals( ( (Player)obj ).Id );

			return base.Equals( obj );
		}

		/// <summary>
		/// Returns a hash code for this instance.
		/// </summary>
		/// <returns>
		/// A hash code for this instance, suitable for use in hashing algorithms and data structures like a hash table. 
		/// </returns>
		public override int GetHashCode()
		{
			return HashHelper.CombineHash( this.Id, this.Name );
		}

		/// <summary>
		/// Gives the players army new action points.
		/// </summary>
		public void GiveNewActionPoints()
		{
			this.Army.ForEach( x => x.ActionPoints.Reset() );
		}

		/// <summary>
		/// Determines whether the specified unit id is a unit of this player.
		/// </summary>
		/// <param name="unitId">The unit id.</param>
		/// <returns>
		///   <c>true</c> if the specified unit id is a unit of the player; otherwise, <c>false</c>.
		/// </returns>
		public bool HasUnit( int unitId )
		{
			return this.Army.Any( x => x.Id.Equals( unitId ) );
		}

		/// <summary>
		/// Determines whether the specified unit id is a unit of this player.
		/// </summary>
		/// <param name="unitId">The unit id.</param>
		/// <returns>
		///   <c>true</c> if the specified unit id is a unit of the player; otherwise, <c>false</c>.
		/// </returns>
		public bool HasUnit( Unit unit )
		{
			if( unit == null )throw new ArgumentNullException( "unit" );
			return this.HasUnit( unit.Id );
		}

		/// <summary>
		/// Determines whether this instance has units.
		/// </summary>
		/// <returns>
		///   <c>true</c> if this instance has units; otherwise, <c>false</c>.
		/// </returns>
		public bool HasUnits()
		{
			return this.Army.Count() > 0;
		}

		#region IPrincipal Member

		/// <summary>
		/// Ruft die Identität des aktuellen Principals ab.
		/// </summary>
		/// <returns>Das dem aktuellen Principal zugeordnete <see cref="T:System.Security.Principal.IIdentity"/>-Objekt.</returns>
		public IIdentity Identity
		{
			get { return this.BattleThisIdentity; }
		}

		/// <summary>
		/// Bestimmt, ob der aktuelle Principal zur angegebenen Rolle gehört.
		/// </summary>
		/// <param name="role">Der Name der Rolle, für die die Mitgliedschaft überprüft werden soll.</param>
		/// <returns>
		/// true, wenn der aktuelle Principal ein Member der angegebenen Rolle ist, andernfalls false.
		/// </returns>
		public bool IsInRole( string role )
		{
			throw new NotImplementedException();
		}
		#endregion

		#endregion
	}
}